import Cookies from 'js-cookie'
import { Plugin } from '@nuxt/types'
import { message, Modal } from 'ant-design-vue'
import OSS from 'ali-oss'
import { GetOneFile, FileSuffix } from '@/utils/tool'
import { Admin } from '@/config/api'
import { initializeAxios } from '@/utils/api'

export interface WAxios {
  $get: (url: string, params?: object) => Promise<any>
  $post: (url: string, params?: object) => Promise<any>
  $put: (url: string, params?: object) => Promise<any>
  $delete: (url: string, id?: string, params?: object) => Promise<any>
  $upImage: (url: string, name: string, e: any, progressFunc?: ProgressFunc) => Promise<any>
  $upOss: (e: any, prefix: string) => Promise<any>
  $ossClient: (e: any, prefix: string) => Promise<any>
  $upOssWithFile: (file: File, prefix: string) => Promise<any>
}

export interface OssClient {
  client: OSS,
  fileName: string,
  file: File,
  url: string
}

export interface ProgressFunc {
  (pro: number): void
}

declare module 'vue/types/vue' {
  interface Vue {
    $wAxios: WAxios
  }
}

declare module '@nuxt/types' {
  interface NuxtAppOptions {
    $wAxios: WAxios
  }
}

declare module 'vuex/types/index' {
  interface Store<S> {
    $wAxios: WAxios
  }
}

// 是否为开发者模式
const dev = process.env.NODE_ENV === 'development'

const wPoint = dev ? console.log : () => {}

const axiosPlugin: Plugin = ({ $axios }, inject) => {
  // 请求拦截器
  $axios.onRequest((config) => {
    wPoint('================= url ==================')
    wPoint(config.url, config.method)
    wPoint('================= 参数 ==================')
    wPoint(config.method === 'get' ? config.params : config.data)
  })

  // 响应拦截器
  $axios.onResponse((response) => {
    const resData = response.data
    if (resData.code === 0 || response.config.url === process.env.OSS_CDN_URL) {
      return Promise.resolve(resData)
    } else {
      if (typeof window !== 'undefined') {
        (message as any).error(resData.msg)
      }
      return Promise.reject(resData)
    }
  })

  // 失败拦截器
  // $axios.onError(() => {
  //   // return Promise.reject(error)
  // })

  // 请求失败
  $axios.onRequestError(() => {
    console.log('onRequestError = ')
    // return Promise.reject(error)
  })

  // 响应失败
  $axios.onResponseError((err) => {
    if (err.response && err.response.status && typeof window !== 'undefined') {
      switch (err.response.status) {
        case 422:
          (message as any).error('参数错误')
          break
        case 401:
          (Modal as any).confirm({
            title: '登录超时',
            content: '是否重新登陆?',
            onOk: () => {
              location.href = '/login'
            }
          })
          break
        case 500:
          (message as any).error(err.response.data.msg)
          break
      }
    }
    return Promise.reject(err)
  })

  const $ossClientWithFile = async (file: File, prefix: string): Promise<OssClient> => {
    const signData: any = await $axios.$get(Admin.ali.ossSgin)
    const imageSuffix = await FileSuffix(file)
    const client = new OSS({
      accessKeyId: signData.AccessKeyId,
      accessKeySecret: signData.AccessKeySecret,
      stsToken: signData.SecurityToken,
      bucket: signData.bucket,
      endpoint: signData.cdn,
      cname: true,
      secure: true
    })
    const fileName = `${prefix}${signData.dateStr}_${signData.uuid}.${imageSuffix}`
    return {
      client,
      fileName,
      file,
      url: `${signData.cdn}/${fileName}`
    }
  }

  const $ossClient = async (e: any, prefix: string): Promise<OssClient> => {
    const file = await GetOneFile(e)
    return $ossClientWithFile(file, prefix)
  }

  const $wAxios: WAxios = {
    $get: (url: string, params = {}) => {
      return $axios.$get(url, { params })
    },
    $post: (url: string, params = {}) => {
      return $axios.$post(url, params, {
        headers: {
          'x-csrf-token': Cookies.get('csrfToken')
        }
      })
    },
    $put: (url: string, params = {}) => {
      return $axios.$put(url, params, {
        headers: {
          'x-csrf-token': Cookies.get('csrfToken')
        }
      })
    },
    $delete: (url: string, id: string = '', params = {}) => {
      return $axios.$delete(`${url}${id}`, {
        params,
        headers: {
          'x-csrf-token': Cookies.get('csrfToken')
        }
      })
    },
    $upImage: (url: string, name: string, e: any, progressFunc?: ProgressFunc) => {
      const file = e.target.files[0]
      // 判断图片大小，超出后直接返回
      const fileSize = file.size
      const maxSize = 2 * 1024 * 1024
      if (fileSize > maxSize) {
        return Promise.reject({ code: 1, msg: '图片大小不能超所2M' }) // eslint-disable-line
      }
      // 创建form对象
      const params = new FormData()
      // 通过append向form对象添加数据
      params.append(name, file, file.name)
      return $axios.$post(url, params, {
        headers: {
          'Content-Type': 'multipart/form-data',
          'x-csrf-token': Cookies.get('csrfToken')
        },
        onUploadProgress (progressEvent) {
          const complete = (progressEvent.loaded / progressEvent.total) * 100
          progressFunc && progressFunc(complete)
        }
      })
    },
    $ossClient,
    /**
     * 阿里云文件上传
     */
    $upOss: async (e: any, prefix: string) => {
      const { client, fileName, url, file } = await $ossClient(e, prefix)
      await client.put(fileName, file)
      return url
    },
    /**
     * 阿里云文件上传
     */
    $upOssWithFile: async (file: File, prefix: string) => {
      const { client, fileName, url } = await $ossClientWithFile(file, prefix)
      await client.put(fileName, file)
      return url
    }
  }

  inject('wAxios', $wAxios)
  initializeAxios($wAxios, $axios)
}

export default axiosPlugin
